# coding: utf-8

import os
import re
import time

import config
import handler.http as httpHandler
import handler.jsonp as jsonHandler
import handler.image as imageHandler
from handler.cookie import CookieHandler
from handler.file import FileHandler
from model.attribute_dict import AttributeDict
from model.utils import current_random, current_timestamp
from handler.selenium_handler import SeleniumHandler

from . import logger


class TaipingyangSpider(object):

    def __init__(self, file_handler=None):
        self.base_url = 'http://service.cpic.com.cn'
        self.query_url = '{0}/policy/queryPolicyForwardPage'.format(self.base_url)
        self.verify_code_url = self.base_url + '/common/generateCaptcha?{0}'
        self.result_url = '{0}/detail/automobieDetail'.format(self.base_url)
        self.start_url = self.query_url
        self.cookie_handler = CookieHandler()
        if file_handler is None:
            file_handler = FileHandler()
        self.file_handler = file_handler

    def __get(self, url):
        self.selenium = SeleniumHandler()
        self.selenium.maximize_window()
        self.selenium.get(url)
        time.sleep(1)
        self.cookies = self.selenium.get_cookies()

    def __get_current_url(self):
        return self.selenium.get_current_url()

    ''' 下载图形验证码 '''
    def __download_to_image(self):
        header_new = config.HEADER
        header_new['Referer'] = self.query_url
        header_new['Cookie'] = self.cookie_handler.list_to_string(self.cookies)
        cookies = httpHandler.get_requests_cookie(self.cookies)
        image_url = self.verify_code_url.format(current_timestamp())
        return imageHandler.download_to_image(image_url, headers=header_new, cookies=cookies)

    ''' 从页面裁剪出图形验证码 '''
    def __screenshot_verify_code_image(self):
        element = self.selenium.get_element('//*[@id="imagesCode"]')
        size = element.size
        location = element.location
        top = int(location['y'])
        left = int(location['x'])
        right = int(left + size['width'])
        bottom = int(top + size['height'])
        data = self.selenium.get_screenshot_as_png()
        image = imageHandler.data_to_image(data)
        new_image = imageHandler.cut_verify_code_image(image, (left, top, right, bottom ))
        return new_image

    ''' 验证码破解 '''
    def __verify_code_crack(self):
        image = self.__screenshot_verify_code_image()
        # pic_dir = os.path.join(BASE_PATH, 'pic')
        # image.save(os.path.join(pic_dir, '{0}.jpg'.format(current_random(0,100))))
        # image = binarizing(image, 170)
        # clear_noise(image)
        imageHandler.binaryzation(image, 150)
        imageHandler.remove_line(image)
        code_string = imageHandler.image_to_string(image)
        if code_string:
            code_array = re.findall(r'[\w]', code_string)
            code = ''.join(code_array)
        else:
            code = ''
        logger.info('verify code:{0}'.format(code))
        return code

    ''' 验证码破解 - request识别 '''
    def __verify_code_request_crack(self):
        image = self.__download_to_image()
        url = 'http://op.juhe.cn/vercode/index'
        params = 'key=37233e918923cd8d8a17fccf87a9b130&codeType=1004&base64Str={0}'.format(imageHandler.image_to_base64(image))
        response = httpHandler.post(url, data=params)
        result_dict = jsonHandler.to_object(response.text)
        code = ''
        if int(result_dict['error_code']) == 0:
            code = result_dict['result']
        return code

    ''' 查询页 '''
    def __query_page(self, policy_no, idcard_no):
        self.selenium.get_element('/html/body/div[3]/div[2]/div[2]/div[1]/a[2]').click()
        self.selenium.get_element('//*[@id="policyNo"]').send_keys(policy_no)
        self.selenium.get_element('//*[@id="identifyNum"]').send_keys(idcard_no)
        while True:
            while True:
                time.sleep(1)
                verify_code = self.__verify_code_crack()
                if verify_code and len(verify_code) == 4:
                    break
                else:
                    # self.selenium.get_element('//*[@id="refresh_icon1"]').click()
                    self.selenium.execute_script('$("#refresh_icon1").click();')
                    time.sleep(2)
            self.selenium.get_element('//*[@id="policy_authCode"]').send_keys(verify_code)
            self.selenium.get_element('//*[@id="forpoliy"]').click()
            time.sleep(1)
            btn_msg_button = self.selenium.execute_script('return $(".btnMsg");')
            if btn_msg_button:
                #msg_text = self.selenium.get_element_text('/html/body/div[7]/p')
                msg_text = self.selenium.execute_script('return $("p.msgTxt").text();')
                if msg_text:
                    logger.info(msg_text)
                    if msg_text.find(u'保单号不匹配') > -1:
                        self.file_handler.write_queried(self.policy_no, 0)
                        logger.info('policy no [{0}] not found info!'.format(self.policy_no))
                        break
                self.selenium.execute_script('$(".btnMsg").click();')
                continue
                #self.selenium.execute_script('''var dialogButton=$(".btnMsg");if(dialogButton)dialogButton.click();''')
            if self.__get_current_url() == self.result_url:
                logger.info('verify code success!')
                self.__result_page()
                break
            time.sleep(1)
            #verify_code_error_element = self.selenium.get_element('/html/body/div[3]/div[2]/div[2]/div[3]/div[3]/span')
            verify_code_error_element_style = self.selenium.execute_script('return $(".p_errorcode").attr("style");')
            if verify_code_error_element_style and verify_code_error_element_style.find('block') > -1:
                # dialog_button = self.selenium.get_element('/html/body/div[7]/div[1]/input')
                # if dialog_button:
                #     dialog_button.click()
                # if self.selenium.exists(By.CLASS_NAME, 'btnMsg') is True:
                #     self.selenium.find_element(By.CLASS_NAME, 'btnMsg').click()
                verify_code_error_msg = self.selenium.execute_script('return $(".p_errorcode").text();')
                logger.info(verify_code_error_msg)
                #self.selenium.get_element('//*[@id="policy_authCode"]').send_keys(u'')
                # self.selenium.get_element('//*[@id="refresh_icon1"]').click()
                self.selenium.execute_script('$("#policy_authCode").val("");$("#refresh_icon1").click();')
                time.sleep(1)

    def __result_page(self):
        try:
            logger.info('current location result page!')
            # 展开所有标签
            # self.selenium.execute_script('$(".m-info p").click();')
            self.selenium.execute_script('$(".u-list").removeAttr("style");')
            # 开始收集数据
            policy_info = AttributeDict()
            policy_no = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[2]/ul/li[1]')
            policy_info.policy_no = policy_no.replace(u'保单号：', '')
            policy_address = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[2]/ul/li[2]')
            policy_info.policy_address = policy_address.replace(u'承保地：', '')
            policy_status = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[2]/ul/li[3]')
            policy_info.policy_status = policy_status.replace(u'保单状态：', '')
            policy_date_time = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[2]/ul/li[4]')
            policy_info.policy_date_time = policy_date_time.replace(u'保单状态：', '')
            policy_info.policy_name = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[1]/div[1]/p/span')
            policy_info.policy_the_name = self.selenium.get_element_text('//*[@id="insuredName"]')
            policy_info.policy_holder_name = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[1]/div[2]/p/span')
            # 责任信息
            li_elements = self.selenium.get_elements('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[1]/ul/li')
            if li_elements and len(li_elements) > 1:
                liability_list = []
                for (index, li_element) in enumerate(li_elements):
                    if index == 0:
                        continue
                    span_elements = li_element.find_elements_by_tag_name('span')
                    liability = AttributeDict()
                    liability.name = span_elements[0].text # 责任名称
                    liability.money = span_elements[1].text # 保额
                    liability.policy_money = span_elements[2].text # 保费
                    # liability.desc = li_element.find_element_by_xpath('[@class="coverageHidden"]/parent::section/text()')
                    desc = self.selenium.execute_script('return $(".coverageInfo li").eq({0}).find(".coverageHidden").text();'.format(index))
                    liability.desc = desc.replace(u'浮动情况', '')
                    liability_list.append(liability)
                policy_info.liability_list = liability_list
            pay_premium = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[3]/ul/li[2]')
            policy_info.pay_premium = pay_premium.replace(u'保费总计：', '')
            paid_premium = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[3]/ul/li[3]')
            policy_info.paid_premium = paid_premium.replace(u'已缴保费金额：', '')
            total_rate_floating = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[3]/ul/li[6]')
            policy_info.total_rate_floating = total_rate_floating.replace(u'浮动系数总计：', '')
            pay_date = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[3]/ul/li[5]')
            policy_info.pay_date = pay_date.replace(u'缴费日期：', '')
            unpaid_premium = self.selenium.get_element_text('/html/body/div[4]/div[2]/div[1]/div/div/div[3]/div/div[3]/ul/li[4]')
            policy_info.unpaid_premium = unpaid_premium.replace(u'欠缴保费金额：', '')
            # 缴费信息
            li_elements = self.selenium.get_elements('//*[@id="endorsePayInfoFirst"]/ul/li')
            if li_elements and len(li_elements) > 1:
                pay_list = []
                for (index, li_element) in enumerate(li_elements):
                    if index == 0:
                        continue
                    span_elements = li_element.find_elements_by_tag_name('span')
                    pay_info = AttributeDict()
                    pay_info.policy_no = span_elements[0].text  # 保单/批单号码
                    pay_info.pay_object = span_elements[1].text # 支付对象
                    pay_info.type = span_elements[2].text # 费用类型
                    pay_info.bank_no = span_elements[3].text  # 银行账号
                    pay_info.pay_money = span_elements[4].text  # 支付金额
                    pay_info.pay_date = span_elements[5].text  # 支付日期
                    pay_list.append(pay_info)
                policy_info.pay_list = pay_list
            # 渠道信息
            spans = self.selenium.get_elements('//*[@id="channelInfoFirst"]/ul/li[2]/span')
            policy_info.channel_type = spans[0].text  # 渠道类型
            policy_info.agency_name = spans[1].text  # 代理机构/人名称
            policy_info.agency_code = spans[2].text  # 机构代码/职业资格证书代码
            policy_info.salesman_code = spans[3].text  # 营销员资格证书代码
            policy_info.payment_method = spans[4].text  # 支付方式
            policy_info.payment_object = spans[5].text  # 支付对象
            # 车辆信息
            license_plate_no = self.selenium.get_element_text('//*[@id="plateNo"]')
            policy_info.license_plate_no = license_plate_no.replace(u'车牌号：', '')
            frame_number = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[2]')
            policy_info.frame_number = frame_number.replace(u'车架号：', '')
            engine_number = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[3]')
            policy_info.engine_number = engine_number.replace(u'发动机号：', '')
            nuclear_load_number = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[6]')
            policy_info.nuclear_load_number = nuclear_load_number.replace(u'车辆核定载客数量：', '')
            nuclear_load_weight = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[5]')
            policy_info.nuclear_load_weight = nuclear_load_weight.replace(u'车辆核定载重质量：', '')
            vehicle_type = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[4]')
            policy_info.vehicle_type = vehicle_type.replace(u'车辆类型：', '')
            vehicle_usage = self.selenium.get_element_text('//*[@id="vehicleInfoFirst"]/ul/li[7]')
            policy_info.vehicle_usage = vehicle_usage.replace(u'使用性质：', '')
            self.file_handler.write_result_json(policy_info)
            logger.info('policy no [{0}] save info!'.format(self.policy_no))
        finally:
            self.selenium.back()

    def __handler(self, policy_no, idcard_no):
        self.policy_no = policy_no
        self.idcard_no = idcard_no
        try:
            logger.info('current query policy no: [{0}], idcard no: [{1}]'.format(policy_no, idcard_no))
            self.__query_page(self.policy_no, self.idcard_no)
        except Exception as e:
            logger.log(e)
            logger.error(e)
            # raise e
            # self.__handelr(policy_no, idcard_no)
        logger.info('current query complete!', split=True)

    def run(self, policy_no, idcard_no):
        if self.file_handler.check_queried(policy_no):
            self.__get(self.start_url)
            self.__handler(policy_no, idcard_no)
            self.exit()

    def batch_run(self, query_list):
        logger.info('total of {0} data!'.format(len(query_list)), split=True)
        self.__get(self.start_url)
        for (idcard_no, policy_no) in query_list:
            if self.file_handler.check_queried(policy_no):
                self.__handler(policy_no, idcard_no)
                time.sleep(1)
        self.exit()
        logger.info('all query complete!', split=True)

    def exit(self):
        self.selenium.exit()
